iT邦幫忙

2022 iThome 鐵人賽

DAY 11
2

生命週期

Broker 生命週期

本節將介紹 Broker 的生命週期中,啟動 Broker 與停止 Broker 到底各自發生了什麼事情。

啟動邏輯

當一個 Broker 被啟動時,它將會嘗試與 Transporter 建立連線。建立完成後,它不會將本地服務清單發佈到遠端節點,而是先啟動所有的服務,然後呼叫每個服務中的 started 處理程序。待所有的服務都啟動成功後, Broker 才會將本地服務清單發佈到遠端節點。因此只有在所有本地服務都成功初始化並啟動後,遠端節點才能夠發送請求。


Fig. 1. 啟動 Broker 流程

當兩個服務互相依賴的時候,可能會陷入死結。例如: users 服務設定了 dependencies: ["posts"]posts 也設定了 dependencies: ["users"] 。為避免此狀況,請移除 dependencies 設定,改使用 this.waitForServices 來等待多個服務後再啟動。
補充,官方文件是寫在 started 執行,但筆者測試仍然會死結,建議可以檢查是否有架構設計上的缺陷,或可將微服務再做細分來避免此狀況,例如另外建立一個整合服務來等待兩個服務。

停止邏輯

當呼叫 broker.stop 或停止處理程序時,首先 Broker 會透過 Transporter 發送空的服務列表,這時已停止的服務就不會繼續收到請求,而是將請求改送到其它的實例。接著 Broker 會開始停止所有的本地服務,最後中斷 Transporter 的連線並結束處理程序。


Fig. 2. 停止 Broker 流程

服務生命週期

在介紹完 Broker 的生命週期後,本節將介紹服務的創建、啟動、停止與合併事件,以及該如何使用生命週期事件來做處理。

創建事件處理

created 事件會在服務實例被創建時觸發。例如: broker.createServicebroker.loadService

範例:在服務創建時建立 http 模組實例並存放於 this 中。

const http = require("http");

module.exports = {
    name: "www",
    created() {
        // 建立 HTTP 服務
        this.server = http.createServer(this.httpHandler);
    }
};

注意,這是個同步事件處理函數,不可以返回 Promise ,也不可以使用 async/await 語法糖。

啟動事件處理

started 事件會在呼叫 broker.start 並啟動所有本地服務時被觸發。

範例:用於連線到資料庫。

module.exports = {
    name: "users",
    async started() {
        try {
            await this.db.connect();
        } catch(e) {
            throw new MoleculerServerError("Unable to connect to database.", e.message);
        }
    }
};

注意,這是個非同步事件處理函數,可以返回 Promise ,也可以使用 async/await 語法糖。

停止事件處理

stopped 事件會在呼叫 broker.stop 並停止所有本地服務時被觸發。

範例:用於中斷資料庫連線。

module.exports = {
    name: "users",
    async stopped() {
        try {
            await this.db.disconnect();
        } catch(e) {
            this.logger.warn("Unable to stop database connection gracefully.", e);
        }
    }
};

注意,這是個非同步事件處理函數,可以返回 Promise ,也可以使用 async/await 語法糖。

合併事件處理

merged 事件會在綱目 (包含 mixin ) 合併後被呼叫,呼叫完成後才會將服務註冊,因此你可以在這之前就先對其操作。

module.exports = {
    name: "posts",

    settings: {},

    actions: {
        find: {
            params: {
                limit: "number"
            },
            handler(ctx) {
                // ...
            }
        }
    },

    merged(schema) {
        // 修改服務設定
        schema.settings.myProp = "myValue";
        // 修改 Actions 的驗證參數
        schema.actions.find.params.offset = "number";
    }
};

參考文獻

[1] Lifecycle, https://moleculer.services/docs/0.14/lifecycle.html

家家酒小劇場

  • Otter - 難道不行把程式都寫在一起嗎?
  • Boxy - 生命週期就像妳的人生一樣,在不同階段充分的發揮,才能得到最高的效益!

上一篇
Day 10 : Context
下一篇
Day 12 : Logging
系列文
Moleculer 家家酒31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言